#include "ModelUtil.h"
#include "Mesh.h"
#include "Material.h"
#include "MeshBuffer.h"

namespace steam
{
	namespace coal
	{
		void ModelUtil::addVertex(Face* face, int v1, int v2, int v3)
		{
			face->vIndices.push_back(v1);
			face->vIndices.push_back(v2);
			face->vIndices.push_back(v3);
		}

		void ModelUtil::addNormal(Face* face, int n1, int n2, int n3)
		{
			face->nIndices.push_back(n1);
			face->nIndices.push_back(n2);
			face->nIndices.push_back(n3);
		}

		void ModelUtil::addTexCoord(Face* face, int t1, int t2, int t3)
		{
			face->tIndices.push_back(t1);
			face->tIndices.push_back(t2);
			face->tIndices.push_back(t3);
		}

		IndexVector ModelUtil::getVertexIndices(const IFace* face)
		{
			const Face* f = static_cast<const Face*>(face);
			return f->vIndices;
		}

		IndexVector ModelUtil::getNormalIndices(const IFace* face)
		{
			const Face* f = static_cast<const Face*>(face);
			return f->nIndices;
		}

		IndexVector ModelUtil::getTexCoordIndices(const IFace* face)
		{
			const Face* f = static_cast<const Face*>(face);
			return f->tIndices;
		}

		Mesh* ModelUtil::duplicateMesh(IMesh* mesh, const base::Scale& scale)
		{
			Mesh* newMesh = new Mesh;

			newMesh->setMeshName(mesh->getMeshName().c_str());

			const VertexVector& vertices = mesh->getVertices();
			for (VertexVector::const_iterator cit = vertices.begin(), eit = vertices.end(); cit != eit; ++cit)
			{
				const Vertex& v = *cit;
				Vertex newV; 
				newV.x = v.x * scale.getXFactor(); 
				newV.y = v.y * scale.getYFactor(); 
				newV.z = v.z * scale.getZFactor();
				newMesh->addVertex(newV);
			}

			const NormalVector& normals = mesh->getNormals();
			for (NormalVector::const_iterator cit = normals.begin(), eit = normals.end(); cit != eit; ++cit)
			{
				const Normal& n = *cit;
				newMesh->addNormal(n);
			}

			const TexCoordVector& texCoords = mesh->getTexCoords();
			for (TexCoordVector::const_iterator cit = texCoords.begin(), eit = texCoords.end(); cit != eit; ++cit)
			{
				const TexCoord& t = *cit;
				newMesh->addTexCoord(t);
			}

			const MaterialVector& materials = mesh->getMaterials();
			for (MaterialVector::const_iterator cit = materials.begin(), eit = materials.end(); cit != eit; ++cit)
			{
				const IMaterial* m = *cit;
				Material* newMat = new Material;
				
				newMat->setMaterialName(m->getMaterialName());
				newMat->setAmbientColor(m->getAmbientColor());
				newMat->setDiffuseColor(m->getDiffuseColor());
				newMat->setSpecularColor(m->getSpecularColro());
				newMat->setAmbientTexture(m->getAmbientTexture());
				newMat->setDiffuseTexture(m->getDiffuseTexture());
				newMat->setSpecularTexture(m->getSpecularTexture());
				
				newMesh->addMaterial(newMat);
			}

			unsigned int meshBufferCount = mesh->getMeshBufferCount();
			for (unsigned int i = 0; i < meshBufferCount; ++i)
			{
				const IMeshBuffer* mBuff = mesh->getMeshBuffer(i);
				MeshBuffer* newMBuff = new MeshBuffer;

				newMBuff->setMeshBufferName(mBuff->getMeshBufferName());
				newMBuff->setMaterialName(mBuff->getMaterialName());

				for (ConstFaceIterator it = mBuff->getFaceStartIter(); it != mBuff->getFaceEndIter(); ++it)
				{
					const IFace* face = *it;
					Face* newFace = new Face;

					IndexVector& vertexIndices = ModelUtil::getVertexIndices(face);
					if (vertexIndices.size() == 3)
					{
						ModelUtil::addVertex(newFace, vertexIndices[0], vertexIndices[1], vertexIndices[2]);
					}
					IndexVector& normalIndices = ModelUtil::getNormalIndices(face);
					if (normalIndices.size() == 3)
					{
						ModelUtil::addNormal(newFace, normalIndices[0], normalIndices[1], normalIndices[2]);
					}
					IndexVector& texCoordIndices = ModelUtil::getTexCoordIndices(face);
					if (texCoordIndices.size() == 3)
					{
						ModelUtil::addTexCoord(newFace, texCoordIndices[0], texCoordIndices[1], texCoordIndices[2]);
					}

					newMBuff->addFace(newFace);
				}
				newMesh->addMeshBuffer(newMBuff);
			}

			return newMesh;
		}

	}
}